﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.Timers;
using Reborn_WorldServer;

namespace Reborn_Server.App1AppHandler
{
    public class Buff : TargetSpell
    {
        protected Timer spellTimer = new Timer(1000 * 60);

        //Used for beneficial spells to indicate duration
        public int minutesLeft = 0;

        //Used for spells that dont indicate a duration to the client (usually detrimental)
        public int ticksLeft = 0;
        public bool useTicksAsMinutes = false;

        public bool saveBuff = true;

        public Buff():base() 
        {
            spellTimer.AutoReset = false;
            spellTimer.Elapsed += new ElapsedEventHandler(SpellTimer_Expired);
        }

        public virtual int GetOptionalValue()
        {
            return -1;
        }
        public virtual string GetXmlData()
        {
            return "";
        }

        public virtual void Resume(CreatureBase targetCreatureBase, SpellIcon _spellIcon, int timeRemaining, int castLevel, int castCharacterID, int castInt, int castWis, int optionalValue, string xmlData)
        {
            base.CastingCharacterID = castCharacterID;
            base.CastingCreatureInt = castInt;
            base.CastingCreatureWis = castWis;
            base.CastingCreatureLevel = castLevel;

            TargetCreatureBase = targetCreatureBase;
            SpellID = targetCreatureBase.GameHandler.ItemIDGen.GetSpellID();

            spellIcon = _spellIcon;

            targetCreatureBase.buffManager.AddBuff(this);
        }

        //Checks if cast is valid (has enough mana, target in range.. etc)
        //Sets references to Caster, Target, Icon, Unique ID
        //Reduces Mana, Removes Warmed Spell
        //!!DOES NOT SEND ANY UPDATES!!
        //      Updates will be handled by the subclass to prevent double updates
        //Locking (Thread Safety) is handled by the caller

        //Stores the buff that gets overwriten by this cast incase the new buff needs data from it
        private Buff _overwrittenBuff = null;
        protected Buff overwrittenBuff
        {
            get { return _overwrittenBuff; }
            set { _overwrittenBuff = value; }
        }

        private void updateSpell()
        {
            //Add Buff to creature base
            TargetCreatureBase.buffManager.AddBuff(this);

            if (spellIcon.StackType != "")
            {
                foreach (Buff buff in TargetCreatureBase.buffManager.Buffs)
                {
                    if (buff.spellIcon.StackType == base.spellIcon.StackType &&
                        buff.spellIcon.Offensive == base.spellIcon.Offensive &&
                        buff.SpellID != SpellID)
                    {
                        _overwrittenBuff = buff;
                        buff.RemoveSpell(false, false);
                        break;
                    }
                }
            }

            //Update CreatureBase to update buffs in creature list
            foreach (MapItem mapitem in TargetCreatureBase.currentMapItem.mapItemsWithin4)
            {
                if (Math.Abs(mapitem.MapX - TargetCreatureBase.MapX) <= 4 && Math.Abs(mapitem.MapY - TargetCreatureBase.MapY) <= 4)
                {
                    foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                    {
                        if (creatureBase is Character)
                        {
                            Character charToUpdate = (Character)creatureBase;
                            charToUpdate.AddCreatureBase(TargetCreatureBase);
                        }
                    }
                }
            }
        }

        protected override bool InitializeInstantCast(CreatureBase myCreatureBase, CreatureBase _targetCreatureBase, SpellIcon sIcon, int CastLevel, bool sendMessages)
        {
            if (base.InitializeInstantCast(myCreatureBase, _targetCreatureBase, sIcon, CastLevel, sendMessages) == false)
                return false;

            updateSpell();

            return true;
        }
        protected override bool InitializeCast(CreatureBase myCreatureBase, int CastLevel, long CreatureGUID, bool sendMessages, out List<MapItem> MapItemsWithin12)
        {
            if (base.InitializeCast(myCreatureBase, CastLevel, CreatureGUID, sendMessages, out MapItemsWithin12) == false)
                return false;

            updateSpell();

            return true;
        }


        //This is overriden in the spell subclass to make the appropriate adjustments to the
        //creature when the spell is removed
        public virtual void RemoveSpell(bool updateBuffs, bool sendMessage)
        {
            LockItem lockItem = Managers.GameHandler.GetLockItem(TargetCreatureBase.MapID, TargetCreatureBase.Instance);
            lock (lockItem.LockObj)
            {
                spellTimer.Stop();
                spellTimer.Dispose();
                TargetCreatureBase.buffManager.RemoveBuff(this);

                if (updateBuffs == true)
                {
                    TargetCreatureBase.buffManager.UpdateBuffs();

                    foreach (MapItem mapitem in TargetCreatureBase.currentMapItem.mapItemsWithin4)
                    {
                        if (Math.Abs(mapitem.MapX - TargetCreatureBase.MapX) <= 4 && Math.Abs(mapitem.MapY - TargetCreatureBase.MapY) <= 4)
                        {
                            foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                            {
                                if (creaturebase is Character)
                                {
                                    Character charToUpdate = (Character)creaturebase;
                                    charToUpdate.AddCreatureBase(TargetCreatureBase);
                                }
                            }
                        }
                    }
                }

                if (sendMessage == true)
                {
                    TargetCreatureBase.SendMessage(base.spellIcon.Name + " has worn off you", "spelldefense");
                    if (!(TargetCreatureBase is Character && TargetCreatureBase.ID == CastingCharacterID))
                        Managers.GameHandler.TrySendMessage(CastingCharacterID, base.spellIcon.Name + " has worn off " + TargetCreatureBase.Name, "spelldefense");
                }
            }
        }

        //Standard timer handler for buff spell, de-increments the timer updates the minutes
        //This will be overriden for spells using a tick timer (not minutes) or that do stuff on the timer intervals
        protected virtual void SpellTimer_Expired(object source, ElapsedEventArgs e)
        {
            LockItem lockitem = TargetCreatureBase.GameHandler.GetLockItem(TargetCreatureBase.MapID, TargetCreatureBase.Instance);

            lock (lockitem.LockObj)
            {
                //This buff has been removed, do nothing (this can occur if the buff gets overwritten exactly when this timer fires)
                if (TargetCreatureBase.buffManager.hasBuff(this.SpellID) == false)
                    return;

                if (useTicksAsMinutes == false)
                {
                    if (minutesLeft > 1)
                    {
                        minutesLeft--;
                        TargetCreatureBase.buffManager.UpdateBuffs();
                        spellTimer.Start();
                    }
                    else
                        RemoveSpell(true, true);
                }
                else
                {
                    if (ticksLeft > 1)
                    {
                        ticksLeft--;
                        spellTimer.Start();
                    }
                    else
                        RemoveSpell(true, true);
                }
            }
        }
    }
}
